# Icon

Bumbag aims to have a **low bundle size** & be **icon agnostic**, hence it does not come with a default icon set (apart from status icons).

You will need to bring your own icon set. Below is a guide & example to import the **Free Font Awesome** icon set.

There are two ways to import icons for the `<Icon>` component. You can either:

- [Inject the icons via the Bumbag Theme](#usage-via-bumbag-theme) **(recommended)**, or
- [Import the icon directly](#usage-via-direct-import), or
- [Use SVG paths](#usage-via-svg-paths)

## Import

```js
import { Icon } from 'bumbag';
```

## Usage via Bumbag Theme

**Note**: Bumbag currently only supports parsing of **Font Awesome** icons. If you want to use another icon set, you will need to follow the [usage via SVG paths](#usage-via-svg-paths) instructions. Want to add a parser or an icon set? [Open a Pull Request](https://github.com/bumbagui/bumbag/pulls).

**First**, you will need to inject the icons your app will use into the [Bumbag Theme](/styling#theming)

This example uses [@fortawesome/free-solid-svg-icons](https://www.npmjs.com/package/@fortawesome/free-solid-svg-icons) and [@fortawesome/free-regular-svg-icons](https://www.npmjs.com/package/@fortawesome/free-regular-svg-icons).

```jsx
import { Provider as BumbagProvider } from 'bumbag';
import { faIgloo, faSearch, faClipboard, faThumbsUp } from '@fortawesome/free-solid-svg-icons';
import { faAddressBook } from '@fortawesome/free-regular-svg-icons';

const theme = {
  icons: {
    iconSets: [
      {
        icons: [faIgloo, faSearch, faClipboard, faThumbsUp],
        prefix: 'solid-',
        type: 'font-awesome'
      },
      {
        icons: [faAddressBook],
        prefix: 'regular-',
        type: 'font-awesome'
      }
    ]
  }
};

export default () => <BumbagProvider theme={theme}><App/></BumbagProvider>
```

**Then**, you can use your icons like so:

```jsx-live
  <Icon aria-label="Settings" icon="solid-igloo" />
```

## Usage via Direct Import

You can also import the icons when you need them:

```jsx
import { faPen } from '@fortawesome/free-solid-svg-icons'

<Icon aria-label="Settings" icon={faPen} type="font-awesome" />
```

## Usage with SVG paths

Currently, Bumbag only supports parsing of **Font Awesome** icons, but if you want to use another icon set, you will need to use SVG paths.

You can supply your SVG paths through the **Bumbag Theme** or **on the icon directly**.

#### Via the Bumbag Theme

Here is an example for a calendar icon:

```jsx
import { ThemeProvider } from 'bumbag';
import { faIgloo, faSearch, faClipboard, faThumbsUp } from '@fortawesome/free-solid-svg-icons';
import { faAddressBook } from '@fortawesome/free-regular-svg-icons';

const theme = {
  icons: {
    icons: {
      calendar: {
        viewBoxWidth: 16,
        viewBoxHeight: 16,
        paths: ['M11 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1s-1 .4-1 1v1c0 .5.4 1 1 1zm3-2h-1v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H6v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H1c-.6 0-1 .5-1 1v12c0 .6.4 1 1 1h13c.6 0 1-.4 1-1V2c0-.6-.5-1-1-1zM5 13H2v-3h3v3zm0-4H2V6h3v3zm4 4H6v-3h3v3zm0-4H6V6h3v3zm4 4h-3v-3h3v3zm0-4h-3V6h3v3zM4 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1S3 .4 3 1v1c0 .5.4 1 1 1z']
      }
    }
  }
};

export default () => (
  <ThemeProvider theme={theme}>
    <App/>
  </ThemeProvider>
);
```

```jsx-live
<Icon aria-label="Calendar" icon="calendar" />
```

#### Via the icon directly

```function-live
function Example() {
  const calendar = {
    viewBoxWidth: 16,
    viewBoxHeight: 16,
    paths: ['M11 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1s-1 .4-1 1v1c0 .5.4 1 1 1zm3-2h-1v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H6v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H1c-.6 0-1 .5-1 1v12c0 .6.4 1 1 1h13c.6 0 1-.4 1-1V2c0-.6-.5-1-1-1zM5 13H2v-3h3v3zm0-4H2V6h3v3zm4 4H6v-3h3v3zm0-4H6V6h3v3zm4 4h-3v-3h3v3zm0-4h-3V6h3v3zM4 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1S3 .4 3 1v1c0 .5.4 1 1 1z']
  };

  return (
    <Icon aria-label="Calendar" icon={calendar} />
  );
}
```

### Sizes

Change the size of an icon with the `fontSize` prop.

```jsx-live
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="100" />
<Icon aria-label="Igloo" icon="solid-igloo" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="300" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="400" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="500" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="600" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="700" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="800" marginLeft="major-1" />
<Icon aria-label="Igloo" icon="solid-igloo" fontSize="900" marginLeft="major-1" />
```

### Colors

Change the color of an icon with the `color` prop. It can be any color from the [palette](/palette), or any other color like `#ff0000` or `red`.

```jsx-live
<Icon aria-label="Success" icon="success" color="success" />
<Icon aria-label="Error" icon="danger" color="danger" marginLeft="major-1" />
<Icon aria-label="Warning" icon="warning" color="warning" marginLeft="major-1" />
<Icon aria-label="Copy" icon="solid-clipboard" color="primary" marginLeft="major-1" />
```

### Usage in text

Icons will be the same size as its text by default.

```jsx-live
<Text>
  This is text with an icon! <Icon aria-label="Thumbs up" icon="solid-thumbs-up" />
</Text>
<Heading use="h3" marginTop="major-2">
  This is a heading with an icon! <Icon aria-label="Thumbs up" icon="solid-thumbs-up" />
</Heading>
```

## Accessibility

### Rules

- The `Icon` must have an `aria-label` prop, however, if it is a presentational icon with no meaning, set the `aria-hidden` prop to `true`.

#### Patterns

- The `Icon` has a role of `img`.
- If no `aria-label` is provided, then `aria-hidden` is set to `true`.

#### References

- [Semantically identifying a font icon with role="img"](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA24.html)

## Icon Props

<!-- Automatically generated -->

**<Code fontSize="150" marginRight="major-1">color</Code>** <Code fontSize="100" palette="primary">string</Code> 

Color of the icon. Can be a color from the palette, or any other color.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">icon</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | IconDefinition
  | { viewBoxHeight: number; viewBoxWidth: number; paths?: string[]; tree?: any[]; }`}
</Code>

The name of your icon or parsed icon.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">label</Code>** <Code fontSize="100" palette="primary">string</Code> 

A label for the icon which can be read by screen readers. This is required if a11yHidden is false.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">fontSize</Code>** <Code fontSize="100" palette="primary">string</Code> 

Size of the icon.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">type</Code>** <Code fontSize="100" palette="primary">&#34;font-awesome&#34; | &#34;font-awesome-standalone&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

<details><Box use="summary" marginBottom="major-2">Inherits <strong><code>Box</code></strong> props</Box>

**<Code fontSize="150" marginRight="major-1">use</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">className</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">children</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignX</Code>** <Code fontSize="100" palette="primary">&#34;right&#34; | &#34;left&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignY</Code>** <Code fontSize="100" palette="primary">&#34;top&#34; | &#34;bottom&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">variant</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">colorMode</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">disabled</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">overrides</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 96 more ...;
  Template?: TemplateThemeConfig;
}`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">elementRef</Code>** <Code fontSize="100" palette="primary">((instance: any) =&#62; void) | RefObject&#60;any&#62;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">themeKey</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

</details>
            

## Theming

<Theme component={'Icon'} overrides={[{ key: 'Icon.styles.base', props: { icon: 'solid-igloo' } }]} />

<Box marginBottom="major-2"><Code fontWeight="semibold">Icon.iconSets</Code></Box>

<Paragraph>The icons to inject into Bumbag.</Paragraph>

**Schema**

```json
{
  icons: {
    iconSets: [
      {
        icons: Array,
        prefix: string
        type: string
      }
    ]
  }
}
```

**Example**

```json
{
  icons: {
    iconSets: [
      {
        icons: [
          faArrowLeft,
          faArrowRight
        ],
        prefix: 'solid-',
        type: 'font-awesome'
      },
      {
        icons: [
          faIgloo
        ],
        prefix: 'regular-',
        type: 'font-awesome'
      }
    ]
  }
}
```

<Box marginBottom="major-2"><Code fontWeight="semibold">Icon.icons</Code></Box>

<Paragraph>A map of SVG icons.</Paragraph>

**Schema**

```
{
  icons: {
    icons: {
      [iconName: string]: {
        viewBoxHeight: number,
        viewBoxWidth: number,
        paths: [string]
      }
    }
  }
}
```

**Example**

```
{
  icons: {
    icons: {
      calendar: {
        viewBoxWidth: 16,
        viewBoxHeight: 16,
        paths: [
          'M11 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1s-1 .4-1 1v1c0 .5.4 1 1 1zm3-2h-1v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H6v1c0 1.1-.9 2-2 2s-2-.9-2-2V1H1c-.6 0-1 .5-1 1v12c0 .6.4 1 1 1h13c.6 0 1-.4 1-1V2c0-.6-.5-1-1-1zM5 13H2v-3h3v3zm0-4H2V6h3v3zm4 4H6v-3h3v3zm0-4H6V6h3v3zm4 4h-3v-3h3v3zm0-4h-3V6h3v3zM4 3c.6 0 1-.5 1-1V1c0-.6-.4-1-1-1S3 .4 3 1v1c0 .5.4 1 1 1z'
        ]
      }
    }
  }
}
```

<Box marginBottom="major-2"><Code fontWeight="semibold">Icon.iconNames</Code></Box>

<Paragraph>Icon name aliases which map to the proper icon names (so you can use <Code><Icon icon="info" /></Code>).</Paragraph>

<Paragraph>Note: you are able to add more, but these ones are required.</Paragraph>

**Schema**

```
{
  icons: {
    iconNames: {
      info: string,
      warning: string,
      success: string,
      danger: string
      [key: string]: string
    }
  }
}
```

**Example**

```
{
  icons: {
    iconNames: {
      info: 'info-circle',
      warning: 'exclamation-triangle',
      success: 'check-circle',
      danger: 'exclamation-circle'
    }
  }
}
```
